package com.microtf.inscription.metaweblog;

import com.microtf.inscription.metaweblog.xmlrpc.RpcController;
import com.microtf.inscription.metaweblog.xmlrpc.StreamConfig;
import com.microtf.inscription.metaweblog.xmlrpc.TypeFactoryImpl;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.parser.XmlRpcRequestParser;
import org.apache.xmlrpc.serializer.DefaultXMLWriterFactory;
import org.apache.xmlrpc.serializer.XmlRpcWriter;
import org.apache.xmlrpc.serializer.XmlWriterFactory;
import org.apache.xmlrpc.util.SAXParsers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * XmlRpc服务统一接口
 * @author guliuzhong
 */
public class XmlRpcService {
    StreamConfig streamConfig;
    RpcController rpcController;
    final static Logger logger = LoggerFactory.getLogger(XmlRpcService.class);

    public void setStreamConfig(StreamConfig streamConfig) {
        this.streamConfig = streamConfig;
    }

    public void setRpcController(RpcController rpcController) {
        this.rpcController = rpcController;
    }

    /**
     * 解析xml rpc的服务入参
     * @param inputStream 入参数据流
     * @return rpc入参
     * @throws XmlRpcException 文件流解析xml出错
     * @throws IOException 文件流读取出错
     * @throws SAXException 文件流解析xml出错
     */
    public XmlRpcRequestParser getXmlRequestParser(InputStream inputStream) throws XmlRpcException, IOException, SAXException {
        rpcController.setXmlRpcConfig(streamConfig);
        TypeFactoryImpl typeFactory = new TypeFactoryImpl(rpcController);
        XmlRpcRequestParser parser = new XmlRpcRequestParser(streamConfig, typeFactory);
        XMLReader xr = SAXParsers.newXMLReader();
        xr.setContentHandler(parser);
        InputSource inputSource = new InputSource(inputStream);
        xr.parse(inputSource);
        xr.setContentHandler(parser);
        return parser;
    }

    /**
     * 向客户端发送出错信息
     * @param outputStream 客户端流
     * @param pCode 错误编码
     * @param pMessage 错误说明
     * @author guliuzhong
     * @since 1.0
     */
    public void responseError(OutputStream outputStream, int pCode, String pMessage) {
        rpcController.setXmlRpcConfig(streamConfig);
        XmlWriterFactory writerFactory = new DefaultXMLWriterFactory();
        TypeFactoryImpl typeFactory = new TypeFactoryImpl(rpcController);
        ContentHandler w;
        logger.warn("code {},message{}",pCode,pMessage);
        try {
            w = writerFactory.getXmlWriter(streamConfig, outputStream);
            XmlRpcWriter xmlRpcWriter = new XmlRpcWriter(streamConfig, w, typeFactory);
            xmlRpcWriter.write(streamConfig, pCode, pMessage);
        } catch (XmlRpcException e) {
            logger.error("responseError XmlRpcException {}", e.getMessage());
        } catch (SAXException e) {
            logger.error("responseError SAXException {}", e.getMessage());
        }
    }
    /**
     * 向客户端发送数据
     *
     * @param outputStream 客户端流
     * @param pResult 数据 主要支持map和基础数据类型名string,int等。
     * @author guliuzhong
     * @since 1.0
     */
    public void response(OutputStream outputStream, Object pResult) {
        rpcController.setXmlRpcConfig(streamConfig);
        XmlWriterFactory writerFactory = new DefaultXMLWriterFactory();
        TypeFactoryImpl typeFactory = new TypeFactoryImpl(rpcController);
        ContentHandler w;
        logger.info("result{}",pResult);
        try {
            w = writerFactory.getXmlWriter(streamConfig, outputStream);
            XmlRpcWriter xmlRpcWriter = new XmlRpcWriter(streamConfig, w, typeFactory);
            xmlRpcWriter.write(streamConfig, pResult);
        } catch (XmlRpcException e) {
            logger.error("response XmlRpcException {}", e.getMessage());
        } catch (SAXException e) {
            logger.error("response SAXException {}", e.getMessage());
        }
    }
}
